use anyhow::Result;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

/// 初始化日志系统
pub fn init_logging(
    verbose: bool,
    quiet: bool,
) -> Result<()> {
    let log_level = if quiet {
        "error"
    } else if verbose {
        "debug"
    } else {
        "info"
    };

    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(log_level));

    tracing_subscriber::registry().with(env_filter).with(tracing_subscriber::fmt::layer().with_target(false)).try_init()?;

    Ok(())
}

/// 验证扩展名称
pub fn validate_extension_name(name: &str) -> Result<()> {
    if name.is_empty() {
        anyhow::bail!("扩展名称不能为空");
    }

    if name.len() > 50 {
        anyhow::bail!("扩展名称不能超过50个字符");
    }

    if !name.chars().all(|c| c.is_alphanumeric() || c == '-') {
        anyhow::bail!("扩展名称只能包含字母、数字和连字符");
    }

    if name.starts_with('-') || name.ends_with('-') {
        anyhow::bail!("扩展名称不能以连字符开始或结束");
    }

    if name.contains("--") {
        anyhow::bail!("扩展名称不能包含连续的连字符");
    }

    Ok(())
}

/// 格式化文件大小
pub fn format_file_size(size: u64) -> String {
    const UNITS: &[&str] = &["B", "KB", "MB", "GB"];
    let mut size = size as f64;
    let mut unit_index = 0;

    while size >= 1024.0 && unit_index < UNITS.len() - 1 {
        size /= 1024.0;
        unit_index += 1;
    }

    if unit_index == 0 {
        format!("{} {}", size as u64, UNITS[unit_index])
    } else {
        format!("{:.1} {}", size, UNITS[unit_index])
    }
}

/// 格式化持续时间
pub fn format_duration(duration: std::time::Duration) -> String {
    let secs = duration.as_secs();
    let millis = duration.subsec_millis();

    if secs >= 60 {
        let minutes = secs / 60;
        let seconds = secs % 60;
        format!("{}m {}s", minutes, seconds)
    } else if secs > 0 {
        format!("{}.{:03}s", secs, millis)
    } else {
        format!("{}ms", millis)
    }
}

/// 检查是否为有效的Rust标识符
pub fn is_valid_rust_identifier(name: &str) -> bool {
    if name.is_empty() {
        return false;
    }

    // Rust 标识符必须以字母或下划线开始
    let first_char = name.chars().next().unwrap();
    if !first_char.is_alphabetic() && first_char != '_' {
        return false;
    }

    // 后续字符可以是字母、数字或下划线
    name.chars().skip(1).all(|c| c.is_alphanumeric() || c == '_')
}

/// 转换为有效的Rust标识符
pub fn to_valid_rust_identifier(name: &str) -> String {
    let mut result = String::new();
    let mut first_char = true;

    for c in name.chars() {
        if first_char {
            if c.is_alphabetic() || c == '_' {
                result.push(c);
            } else {
                result.push('_');
                if c.is_alphanumeric() {
                    result.push(c);
                }
            }
            first_char = false;
        } else if c.is_alphanumeric() || c == '_' {
            result.push(c);
        } else if c == '-' {
            result.push('_');
        }
        // 跳过其他非法字符
    }

    if result.is_empty() {
        result = "unnamed".to_string();
    }

    result
}

/// 检查目录是否为空
pub fn is_directory_empty(path: &std::path::Path) -> Result<bool> {
    if !path.exists() {
        return Ok(true);
    }

    if !path.is_dir() {
        anyhow::bail!("路径不是目录: {}", path.display());
    }

    let entries = std::fs::read_dir(path)?;
    Ok(entries.count() == 0)
}

/// 递归计算目录大小
pub fn calculate_directory_size(path: &std::path::Path) -> Result<u64> {
    let mut total_size = 0;

    if path.is_file() {
        return Ok(path.metadata()?.len());
    }

    if path.is_dir() {
        for entry in std::fs::read_dir(path)? {
            let entry = entry?;
            let entry_path = entry.path();
            total_size += calculate_directory_size(&entry_path)?;
        }
    }

    Ok(total_size)
}

/// 安全地创建目录
pub fn create_dir_safely(path: &std::path::Path) -> Result<()> {
    if path.exists() {
        if !path.is_dir() {
            anyhow::bail!("路径已存在但不是目录: {}", path.display());
        }
        return Ok(());
    }

    std::fs::create_dir_all(path)?;
    Ok(())
}

/// 获取相对路径
pub fn get_relative_path(
    path: &std::path::Path,
    base: &std::path::Path,
) -> Result<std::path::PathBuf> {
    path.strip_prefix(base).map(|p| p.to_path_buf()).map_err(|_| anyhow::anyhow!("无法计算相对路径"))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validate_extension_name() {
        assert!(validate_extension_name("djgc").is_ok());
        assert!(validate_extension_name("fbfx-csxm").is_ok());
        assert!(validate_extension_name("test123").is_ok());

        assert!(validate_extension_name("").is_err());
        assert!(validate_extension_name("-invalid").is_err());
        assert!(validate_extension_name("invalid-").is_err());
        assert!(validate_extension_name("invalid--name").is_err());
        assert!(validate_extension_name("invalid_name").is_err()); // 下划线不允许
    }

    #[test]
    fn test_format_file_size() {
        assert_eq!(format_file_size(0), "0 B");
        assert_eq!(format_file_size(1024), "1.0 KB");
        assert_eq!(format_file_size(1024 * 1024), "1.0 MB");
        assert_eq!(format_file_size(1024 * 1024 * 1024), "1.0 GB");
    }

    #[test]
    fn test_is_valid_rust_identifier() {
        assert!(is_valid_rust_identifier("valid"));
        assert!(is_valid_rust_identifier("_valid"));
        assert!(is_valid_rust_identifier("valid123"));
        assert!(is_valid_rust_identifier("valid_name"));

        assert!(!is_valid_rust_identifier("123invalid"));
        assert!(!is_valid_rust_identifier("invalid-name"));
        assert!(!is_valid_rust_identifier(""));
    }

    #[test]
    fn test_to_valid_rust_identifier() {
        assert_eq!(to_valid_rust_identifier("valid"), "valid");
        assert_eq!(to_valid_rust_identifier("invalid-name"), "invalid_name");
        assert_eq!(to_valid_rust_identifier("123invalid"), "_123invalid");
        assert_eq!(to_valid_rust_identifier(""), "unnamed");
        assert_eq!(to_valid_rust_identifier("special!@#"), "special");
    }
}
